'''
这是一个为`ftools.py`做UI界面，为`ftools.py`做的一个交互界面。
`ftools`支持命令行的操作方式,允许单独使用。
本程序是采用`ttkbootstrap`做的UI，并`yaml`进行配置本地存储到`config.yaml`
'''
import os
import ttkbootstrap as ttk
from ttkbootstrap.dialogs import Messagebox
from ttkbootstrap.constants import *
from tkinter.filedialog import askdirectory # path路径浏览器
from ttkbootstrap import utility
import ftools as ft
import yaml

windows_width = 1000
windows_heigh = 600
table_width = 900
table_heigh = 400
workdir_path = os.getcwd()
font_str = "Times New Roman"
#font_str = "阿里巴巴普惠体"
#font_str = "Source Han Sans CN"
config_path = 'config.yaml'
config = {
    'global': {
        'theme': "cosmo",
        'path': workdir_path,
        'recursive': 0,
        'overwrite': 0,
        'autobackup': 0
    },
    'append_string': {
        'folder_flag': 0,
        'location': 1,
        'number_flag': 0,
        'number_str': "001",
        'append_str': "",
        'preview':"文件/Readme.txt ----> 文件/Readme.txt"
    },
    'replace_string': {
        'folder_flag': 0,
        'match_str': "me",
        'replace_str': "",
        'preview':"文件/Readme.txt ----> 文件/Read.txt"
    },
    'replace_extension': {
        'match_ext': ".txt",
        'replace_ext': ".log",
        'preview':"匹配目标的后缀将被更改 Readme.txt ----> readme.log"
    },
    'toggle_case': {
        'folder_flag': 0,
        'lower_case': 1,
        'preview':"文件/Readme.txt ----> 文件/readme.txt"
    }
}

if os.path.exists(config_path):
    with open(config_path, 'r', encoding='utf-8') as file:
        config = yaml.safe_load(file)
        #print("Yaml文件已加载：", config)
else:
    with open(config_path, 'w', encoding='utf-8') as file:
        yaml.dump(config, file, default_flow_style=False)
    print("新的Yaml文件已创建并保存。")

class Application(ttk.Frame):
    def __init__(self,master=None):
        super().__init__(master, padding=15)
        self.master = master
        self.style = ttk.Style() # 定义样式表
        self.pack(fill=BOTH, expand=YES)
        self.create_option() # 全局设置选项
        self.create_addStrToFilename()# 添加字符到文件
        self.create_ReplaceString()   # 文件名操作--替换字符
        self.create_ReplaceExt()      # 文件后缀操作--目标替换后缀
        self.create_upperLowerName()  # 文件/文件夹名大小写转换
        self.master.protocol("WM_DELETE_WINDOW", self.save_data) 
    def create_results_view(self):
        self.newWindows = ttk.Toplevel(self)
        geo = self.master.geometry()# 获取主窗口位置
        x_pos = int(geo.split('+')[1])
        y_pos = int(geo.split('+')[2])+windows_heigh-table_heigh
        self.newWindows.geometry("%dx%d+%d+%d" %(table_width,table_heigh,x_pos,y_pos)) # 设置窗口大小
        self.newWindows.title("文件列表")
        self.new_lf = ttk.Labelframe(self.newWindows, text="文件列表（下面是即将操作的文件列表，双击可以从列表中移除)", padding=8)
        self.new_lf.pack(fill=X, expand=YES, anchor=N)
        self.list_results_view()
        self.commit_results_view()
    def commit_results_view(self):
        self.btn_lf = ttk.Frame(self.new_lf)
        self.btn_lf.pack(fill=X, expand=YES, anchor=E)
        commit_btn = ttk.Button(
            master=self.btn_lf,
            text="确认",
            command=self.on_commit_view,
            bootstyle=SUCCESS,#PRIMARY,SUCCESS,INFO,DANGER,DARK,WARNING,OUTLINE,
            width=8
        )
        commit_btn.pack(side=RIGHT, padx=5, anchor=E)
        cancel_btn = ttk.Button(
            master=self.btn_lf,
            text="取消",
            command=self.on_hidden_view,
            bootstyle=PRIMARY,#PRIMARY,SUCCESS,INFO,DANGER,DARK,WARNING,OUTLINE,
            width=8
        )
        cancel_btn.pack(side=RIGHT, padx=5, anchor=E)
    def list_results_view(self):
        self.res_lf = ttk.Frame(self.new_lf)
        self.res_lf.pack(fill=X, expand=YES, anchor=N)
        self.resultview = ttk.Treeview(
            master=self.res_lf,
            bootstyle=DARK,
            columns=[0, 1, 2, 3, 4],
            show=HEADINGS
        )
        self.resultview.pack(fill=BOTH, expand=YES, pady=10)
        self.resultview.heading(0, text='Source Name', anchor=W)
        self.resultview.heading(1, text='Target Name', anchor=W)
        self.resultview.heading(2, text='Type', anchor=W)
        self.resultview.heading(3, text='Operation', anchor=W)
        self.resultview.heading(4, text='Path', anchor=W)
        self.resultview.column(
            column=0,
            anchor=W,
            width=utility.scale_size(self.res_lf, 150),
            stretch=False
        )
        self.resultview.column(
            column=1,
            anchor=W,
            width=utility.scale_size(self.res_lf, 150),
            stretch=False
        )
        self.resultview.column(
            column=2,
            anchor=N,
            width=utility.scale_size(self.res_lf, 50),
            stretch=False
        )
        self.resultview.column(
            column=3,
            anchor=W,
            width=utility.scale_size(self.res_lf, 100),
            stretch=False
        )
        self.resultview.column(
            column=4,
            anchor=W,
            width=utility.scale_size(self.res_lf, 300)
        )
        self.resultview.bind('<Double-1>', self.deleteItems) #绑定鼠标事件，移除数据
        self.resultview.bind('<Double-3>', self.deleteItems) #绑定鼠标事件，移除数据
        '''
        鼠标左键单击按下    1/Button-1/ButtonPress-1
        鼠标左键单击松开    ButtonRelease-1
        鼠标右键单击      3
        鼠标左键双击      Double-1/Double-Button-1
        鼠标右键双击      Double-3
        '''
    def deleteItems(self,event):
        print ('鼠标事件: deleteItems')
        #print (event)
        for item in self.resultview.selection():
            #print (self.resultview.item(item,"values"))
            print(item)
            self.resultview.delete(item)
    def show_results_view(self):
        print("Show list")
        self.on_show_view()# 显示弹窗,保证 resultview 组件存在
        #self.pack(fill=BOTH, expand=YES)
        child = self.resultview.get_children()
        for item in child:
            self.resultview.delete(item)
        self.list.pop(0)# 删除第一个元素
        for directory,file,newfile,type,operation in self.list:
            try:
                iid = self.resultview.insert(
                    parent='',
                    index=END,
                    values=(file,newfile,type,operation,directory)
                )
                #self.resultview.selection_set(iid) # 选中该行数据
                #self.resultview.see(iid) # 数据可见
            except OSError:
                return
    def on_commit_view(self):
        child = self.resultview.get_children()
        over = self.overwrite.get()
        back = self.autobackup.get()
        length = len(child)
        x_pos = self.newWindows.winfo_x()+table_width-400
        y_pos = self.newWindows.winfo_y()+table_heigh-250
        ask = Messagebox.yesno(f'{length}个文件将被修改，修改之后无法撤销的哦\n请谨慎操作', '确认修改吗？',position=(x_pos,y_pos))
        if ask == '取消' or length ==0:
            print('退出修改操作')
        else :
            print('确认修改操作')
            for item in child:
                args = self.resultview.item(item,"values")
                ft.renamed(args[4],args[0],args[1],over,back)
        self.on_hidden_view()# 隐藏弹窗
    def on_show_view(self):
        #self.create_results_view()
        # 最小化窗口 iconify() <--> deiconify()
        # 移除/隐藏窗口 withdraw() <--> deiconify()
        # 销毁组件/窗口 destroy() 销毁所有子窗口、删除主窗口中的所有部件
        # 关闭GUI窗口 quit() 不会销毁子窗口，也不会删除主窗口中的所有部件
        # 隐藏组件 pack_forget() <--> pack()
        # 强制刷新窗口 update()
        #if not hasattr(self, 'newWindows'):
        self.create_results_view()
        self.newWindows.deiconify()
        print("Show Windows")
    def on_hidden_view(self):
        if hasattr(self, 'newWindows'):
            self.newWindows.destroy()
        self.master.update()
        print("Hidden Windows")
    def appendstr_cb(self):
        content = self.append_str.get()
        num = self.number.get()
        location = self.location.get()
        src = '文件夹/Readme ----> 文件夹'
        tar = '文件/Readme.txt ----> 文件'
        if num == 1:
            numstr = self.numstr.get()
        else:
            numstr=''
        if location == 0:
            str = f'{src}/{numstr}{content}Readme' if self.folder1.get() else f'{tar}/{numstr}{content}Readme.txt'
        else:
            str = f'{src}/Readme{content}{numstr}' if self.folder1.get() else f'{tar}/Readme{content}{numstr}.txt'
        self.ex_addstr.set(str)
    def replacestr_cb(self):
        matstr = self.matchstr.get()
        substr = self.substr.get()
        if matstr=='':
            src = f'匹配字符不可为空！'
            tar = f'替换字符允许为空！'
        elif matstr in 'Readme':
            src='Readme'
            tar=src.replace(matstr,substr)
        else:
            src=f'Read{matstr}me'
            tar=src.replace(matstr,substr)
        str = f'文件夹/{src} ----> 文件夹/{tar}' if self.folder2.get() else f'文件/{src}.txt ----> 文件/{tar}.txt'
        self.ex_machsub.set(str)
    def chgext_cb(self):
        matstr = self.matchext.get()
        substr = self.subext.get()
        if matstr=='' or matstr=='.':
            str =f'匹配后缀不可为空！星号‘*’可匹配所有后缀(匹配所有文件)'
        elif matstr=='*':
            str =f'所有文件的后缀将被更改(*.*) ----> *{substr}'
        elif substr=='':
            str =f'匹配目标的后缀将被删除 Readme.{substr} ----> Readme'
        else:
            str =f'匹配目标的后缀将被更改 Readme{matstr} ----> Readme{substr}'
        self.ex_machext.set(str)
    def lower_cb(self):
        lower = self.lower.get()
        folder = self.folder.get()
        if folder==0:
            src = f'文件/Readme'
            ext = f'.txt'
        else:
            src = f'文件夹/Readme'
            ext = f''
        if lower==0:
            str = f'{src}{ext} ----> {src.upper()}{ext}'
        else:
            str = f'{src}{ext} ----> {src.lower()}{ext}'
        self.ex_upper.set(str)
    def create_option(self):
        """Add path row to labelframe"""
        # application variables
        option_text = "全局设置"
        self.option_lf = ttk.Labelframe(self, text=option_text, padding=8)
        self.option_lf.pack(fill=X, expand=YES, anchor=N)
        self.curr_path = ttk.StringVar(value=config['global'].get('path','D:\\WorkDir'))# 操作路径
        self.recursive = ttk.IntVar(value=config['global'].get('recursive',0)) # 是否递归子目录
        self.overwrite = ttk.IntVar(value=config['global'].get('overwrite',0)) # 冲突时是否覆盖
        self.autobackup = ttk.IntVar(value=config['global'].get('autobackup',0)) # 是否备份原文件
        self.theme = config['global'].get('theme','cosmo')
        self.create_path_row()# 目录
        self.create_option_row()# 设置
    def create_path_row(self):
        """Add path row to labelframe"""
        path_row = ttk.Frame(self.option_lf)
        path_row.pack(fill=X, expand=YES)
        path_lbl = ttk.Label(path_row, text="操作目录", width=8)
        path_lbl.pack(side=LEFT, padx=(15, 0))
        path_ent = ttk.Entry(path_row, textvariable=self.curr_path, width=70)
        path_ent.pack(side=LEFT, fill=X,  padx=5)
        browse_btn = ttk.Button(
            master=path_row,
            text="选择路径",
            command=self.on_browse,
            width=8
        )
        browse_btn.pack(side=RIGHT, padx=5)
    def on_browse(self):
        """Callback for directory browse"""
        path = askdirectory(title="选择操作目录")
        if path:
            self.curr_path.set(path)
    def create_option_row(self):
        """Add option setting row to labelframe"""
        option_row = ttk.Frame(self.option_lf)
        option_row.pack(fill=X, expand=YES)
        option_lbl = ttk.Label(option_row, text="其他选项", width=8)
        option_lbl.pack(side=LEFT, padx=(15, 0))
        recursive_opt = ttk.Checkbutton(
            master=option_row,
            text="遍历子目录",
            variable=self.recursive,
        )
        recursive_opt.pack(side=LEFT, padx=5)
        overwrite_opt = ttk.Checkbutton(
            master=option_row,
            text="发生冲突时覆盖文件",
            variable=self.overwrite,
        )
        overwrite_opt.pack(side=LEFT, padx=5)
        autobackup_opt = ttk.Checkbutton(
            master=option_row,
            text="备份原文件(会在操作目录下创建backup目录)",
            variable=self.autobackup,
        )
        autobackup_opt.pack(side=LEFT, padx=5)
    def create_addStrToFilename(self):
        """Add file operation row to labelframe"""
        # application variables
        option_text = "方式1：添加字符到文件名 (修改文件名，往文件名的头部或者尾部添加字符)"
        self.addstr_lf = ttk.Labelframe(self, text=option_text, padding=8)
        self.addstr_lf.pack(fill=X, expand=YES, anchor=N)
        self.folder1 = ttk.IntVar(value=config['append_string'].get('folder_flag',0)) # 文件/文件夹
        self.location = ttk.IntVar(value=config['append_string'].get('location',1))
        self.number = ttk.IntVar(value=config['append_string'].get('number_flag',0))
        self.numstr = ttk.StringVar(value=config['append_string'].get('number_str','001'))
        self.append_str = ttk.StringVar(value=config['append_string'].get('append_str',''))
        self.ex_addstr = ttk.StringVar(value=config['append_string'].get('preview',''))# 效果示例
        self.commit_addstr_row()# 添加 字符组件
        self.example_addstr_row()
        self.folder1.trace("w", lambda name, index, mode,:self.appendstr_cb())
        self.location.trace("w", lambda name, index, mode,:self.appendstr_cb())
        self.number.trace("w", lambda name, index, mode,:self.appendstr_cb())
        self.numstr.trace("w", lambda name, index, mode,:self.appendstr_cb())
        self.append_str.trace("w", lambda name, index, mode,:self.appendstr_cb())
    def commit_addstr_row(self):
        """Add term row to labelframe"""
        add_row = ttk.Frame(self.addstr_lf)
        add_row.pack(fill=X, expand=YES)#, pady=15)

        addstr_lbl = ttk.Label(add_row, text="添加字符", width=8)
        addstr_lbl.pack(side=LEFT, padx=(15, 0))
        addstr_ent = ttk.Entry(add_row, textvariable=self.append_str)
        addstr_ent.pack(side=LEFT, padx=4)

        start_opt = ttk.Radiobutton(
            master=add_row,
            text="添加到头",
            variable=self.location,
            value=0
        )
        start_opt.pack(side=LEFT,padx=4)
        end_opt = ttk.Radiobutton(
            master=add_row,
            text="添加到尾",
            variable=self.location,
            value=1
        )
        end_opt.pack(side=LEFT,padx=4)
        number_add = ttk.Checkbutton(
            master=add_row,
            text="数字递增",
            variable=self.number,
        )
        number_add.pack(side=LEFT,padx=4)

        numstr_ent = ttk.Entry(add_row, textvariable=self.numstr, width=8)
        numstr_ent.pack(side=LEFT, padx=(2,4))
        files_opt = ttk.Radiobutton(
            master=add_row,
            text="文件",
            variable=self.folder1,
            value=0
        )
        files_opt.pack(side=LEFT,padx=5)
        folder_opt = ttk.Radiobutton(
            master=add_row,
            text="文件夹",
            variable=self.folder1,
            value=1
        )
        folder_opt.pack(side=LEFT,padx=5)
        addstr_btn = ttk.Button(
            master=add_row,
            text="预览",
            command=self.on_addstr,
            bootstyle=PRIMARY,#SUCCESS,INFO,DANGER,DARK,WARNING,OUTLINE,
            width=8
        )
        addstr_btn.pack(side=RIGHT, padx=5)
    def example_addstr_row(self):
        call_lbl = ttk.Label(self.addstr_lf, text="效果示例", width=8)
        call_lbl.pack(side=LEFT, padx=(15, 0))
        call_ent = ttk.Label(self.addstr_lf, textvariable=self.ex_addstr)
        call_ent.pack(side=LEFT, fill=X, expand=YES, padx=4)
    def on_addstr(self):
        path = self.curr_path.get()
        recu = self.recursive.get()
        folder = self.folder1.get()
        app_str = self.append_str.get()
        locate = self.location.get()
        number = self.number.get()
        numstr = self.numstr.get() if number else ''
        if path == '':
            return
        if folder == 1 :
            self.list = ft.append_chars_to_foldersname(path,app_str,locate,recu,numstr)
        else:
            self.list = ft.append_chars_to_filename(path,app_str,locate,recu,numstr)
        self.show_results_view()
        print("Append file string")
    def create_ReplaceString(self):
        """Add file operation row to labelframe"""
        # application variables
        option_text = "方式2：替换文件名中的字符 (将目录下，所有匹配的文件名匹配的那部分替换为新的字符)"
        self.substr_lf = ttk.Labelframe(self, text=option_text, padding=8)
        self.substr_lf.pack(fill=X, expand=YES, anchor=N)
        self.folder2 = ttk.IntVar(value=config['replace_string'].get('folder_flag',0)) # 文件/文件夹
        self.matchstr = ttk.StringVar(value=config['replace_string'].get('match_str','me'))
        self.substr = ttk.StringVar(value=config['replace_string'].get('replace_str',''))
        self.ex_machsub = ttk.StringVar(value=config['replace_string'].get('preview',''))# 效果示例
        self.commit_matchsub_row()# 匹配目标、替换字符
        self.example_matchsub_row()
        self.matchstr.trace("w", lambda name, index, mode,:self.replacestr_cb())
        self.substr.trace("w", lambda name, index, mode,:self.replacestr_cb())
        self.folder2.trace("w", lambda name, index, mode,:self.replacestr_cb())
    def commit_matchsub_row(self):
        """Add term row to labelframe"""
        match_row = ttk.Frame(self.substr_lf)
        match_row.pack(fill=X, expand=YES)
        match_lbl = ttk.Label(match_row, text="匹配字符", width=8)
        match_lbl.pack(side=LEFT, padx=(15, 0))
        match_ent = ttk.Entry(match_row, textvariable=self.matchstr)
        match_ent.pack(side=LEFT, padx=5)

        sub_lbl = ttk.Label(match_row, text="替换字符", width=8)
        sub_lbl.pack(side=LEFT, padx=(15, 0))
        sub_ent = ttk.Entry(match_row, textvariable=self.substr)
        sub_ent.pack(side=LEFT, padx=5)

        files_opt = ttk.Radiobutton(
            master=match_row,
            text="文件",
            variable=self.folder2,
            value=0
        )
        files_opt.pack(side=LEFT,padx=5)
        folder_opt = ttk.Radiobutton(
            master=match_row,
            text="文件夹",
            variable=self.folder2,
            value=1
        )
        folder_opt.pack(side=LEFT,padx=5)

        replace_btn = ttk.Button(
            master=match_row,
            text="预览",
            command=self.on_ReplaceStr,
            bootstyle=PRIMARY,#SUCCESS,INFO,DANGER,DARK,WARNING,OUTLINE,
            width=8
        )
        replace_btn.pack(side=RIGHT, padx=5)
    def example_matchsub_row(self):
        call_lbl = ttk.Label(self.substr_lf, text="效果示例", width=8)
        call_lbl.pack(side=LEFT, padx=(15, 0))
        call_ent = ttk.Label(self.substr_lf, textvariable=self.ex_machsub)
        call_ent.pack(side=LEFT, fill=X, expand=YES, padx=4)
    def on_ReplaceStr(self):
        path = self.curr_path.get()
        recu = self.recursive.get()
        folder = self.folder2.get()
        match = self.matchstr.get()
        sub = self.substr.get()
        if path == '' or match=='':
            return
        if folder == 1 :
            self.list = ft.replace_chars_from_foldersname(path,match,sub,recu)
        else:
            self.list = ft.replace_chars_from_filename(path,match,sub,recu)
        self.show_results_view()
        print("Replace file string")
    def create_ReplaceExt(self):
        """Change file operation row to labelframe"""
        # application variables
        option_text = "方式3：文件后缀替换  (操作目录下，**匹配后缀**的文件将被替换后缀，文件扩展名发生改变)"
        self.chgext_lf = ttk.Labelframe(self, text=option_text, padding=8)
        self.chgext_lf.pack(fill=X, expand=YES, anchor=N)
        self.matchext = ttk.StringVar(value=config['replace_extension'].get('match_ext','.txt')) # 匹配后缀
        self.subext = ttk.StringVar(value=config['replace_extension'].get('replace_ext','.log')) # 替换后缀
        self.ex_machext = ttk.StringVar(value=config['replace_extension'].get('preview',''))# 效果示例
        self.commit_matchext_row()# 匹配目标后缀、替换后缀
        self.example_matchext_row()
        self.matchext.trace("w", lambda name, index, mode,:self.chgext_cb())
        self.subext.trace("w", lambda name, index, mode,:self.chgext_cb())
    def commit_matchext_row(self):
        """Add term row to labelframe"""
        match_row = ttk.Frame(self.chgext_lf)
        match_row.pack(fill=X, expand=YES)#, pady=15)

        match_lbl = ttk.Label(match_row, text="匹配后缀", width=8)
        match_lbl.pack(side=LEFT, padx=(15, 0))
        match_ent = ttk.Entry(match_row, textvariable=self.matchext)
        match_ent.pack(side=LEFT, padx=5)

        sub_lbl = ttk.Label(match_row, text="替换后缀", width=8)
        sub_lbl.pack(side=LEFT, padx=(15, 0))
        sub_ent = ttk.Entry(match_row, textvariable=self.subext)
        sub_ent.pack(side=LEFT, padx=5)

        replace_btn = ttk.Button(
            master=match_row,
            text="预览",
            command=self.on_ReplaceExt,
            bootstyle=PRIMARY,#SUCCESS,INFO,DANGER,DARK,WARNING,OUTLINE,
            width=8
        )
        replace_btn.pack(side=RIGHT, padx=5)
    def example_matchext_row(self):
        call_lbl = ttk.Label(self.chgext_lf, text="效果示例", width=8)
        call_lbl.pack(side=LEFT, padx=(15, 0))
        call_ent = ttk.Label(self.chgext_lf, textvariable=self.ex_machext)
        call_ent.pack(side=LEFT,padx=4)
    def on_ReplaceExt(self):
        path = self.curr_path.get()
        recu = self.recursive.get()
        match = self.matchext.get()
        sub = self.subext.get()
        if path == '' or match =='' or match=='.':
            return
        if match =='*' and sub != '':
            self.list = ft.append_ext_to_filename(path,sub,recu) # 匹配所有文件，Append Ext string
        else:
            self.list = ft.replace_ext_from_filename(path,match,sub,recu)# 匹配后缀
        self.show_results_view()
        print("Replace Ext string")
    def create_upperLowerName(self):
        """Change file operation row to labelframe"""
        # application variables
        option_text = "方式4：文件/文件夹大小写转换  (操作目录下，将文件名/文件夹名重置为大写/小写, 仅对字母有效)"
        self.upper_lf = ttk.Labelframe(self, text=option_text, padding=8)
        self.upper_lf.pack(fill=X, expand=YES, anchor=N)
        self.folder = ttk.IntVar(value=config['toggle_case'].get('folder_flag',0)) # 文件/文件夹
        self.lower = ttk.IntVar(value=config['toggle_case'].get('lower_case',1)) # 大写/小写
        self.ex_upper = ttk.StringVar(value=config['toggle_case'].get('preview',''))# 效果示例
        self.commit_uplower_row()  # 匹配目标后缀并删除、添加统一的后缀
        self.example_upper_row()
        self.folder.trace("w", lambda name, index, mode,:self.lower_cb())
        self.lower.trace("w", lambda name, index, mode,:self.lower_cb())
    def commit_uplower_row(self):
        """Add term row to labelframe"""
        upper_row = ttk.Frame(self.upper_lf)
        upper_row.pack(fill=X, expand=YES)#, pady=15)
        uppstr_lbl = ttk.Label(upper_row, text="目标选项", width=8)
        uppstr_lbl.pack(side=LEFT, padx=(15, 0))
        files_opt = ttk.Radiobutton(
            master=upper_row,
            text="文件/Files",
            variable=self.folder,
            value=0
        )
        files_opt.pack(side=LEFT,padx=8)
        folder_opt = ttk.Radiobutton(
            master=upper_row,
            text="文件夹/Folder",
            variable=self.folder,
            value=1
        )
        folder_opt.pack(side=LEFT,padx=8)
        lower_opt = ttk.Radiobutton(
            master=upper_row,
            text="转为小写",
            variable=self.lower,
            value=1
        )
        lower_opt.pack(side=LEFT,padx=8)
        upper_opt = ttk.Radiobutton(
            master=upper_row,
            text="转为大写",
            variable=self.lower,
            value=0
        )
        upper_opt.pack(side=LEFT,padx=8)
        upper_btn = ttk.Button(
            master=upper_row,
            text="预览",
            command=self.on_UpperCase,
            bootstyle=PRIMARY,
            width=8
        )
        upper_btn.pack(side=RIGHT, padx=5)
    def example_upper_row(self):
        call_lbl = ttk.Label(self.upper_lf, text="效果示例", width=8)
        call_lbl.pack(side=LEFT, padx=(15, 0))
        call_ent = ttk.Label(self.upper_lf, textvariable=self.ex_upper)
        call_ent.pack(side=LEFT, padx=5)
    def on_UpperCase(self):
        path = self.curr_path.get()
        recu = self.recursive.get()
        lower = self.lower.get()
        folder = self.folder.get()
        if path == '' or folder=='' or lower=='':
            return
        if folder==1 :
            self.list = ft.rename_folders_to_lowercase(path,lower,recu)
        else:
            self.list = ft.rename_file_to_lowercase(path,lower,recu)
        self.show_results_view()
        print("Upper/lower Case")
    def save_data(self):
        print("Saving config data")
        config['global']['theme'] = self.theme
        config['global']['path'] = self.curr_path.get()
        config['global']['recursive'] = self.recursive.get()
        config['global']['overwrite'] = self.overwrite.get()
        config['global']['autobackup'] = self.autobackup.get()
        config['append_string']['folder_flag'] = self.folder1.get()
        config['append_string']['location'] = self.location.get()
        config['append_string']['number_flag'] = self.number.get()
        config['append_string']['number_str'] = self.numstr.get()
        config['append_string']['append_str'] = self.append_str.get()
        config['append_string']['preview'] = self.ex_addstr.get()
        config['replace_string']['folder_flag'] = self.folder2.get()
        config['replace_string']['match_str'] = self.matchstr.get()
        config['replace_string']['replace_str'] = self.substr.get()
        config['replace_string']['preview'] = self.ex_machsub.get()
        config['replace_extension']['match_ext'] = self.matchext.get()
        config['replace_extension']['replace_ext'] = self.subext.get()
        config['replace_extension']['preview'] = self.ex_machext.get()
        config['toggle_case']['folder_flag'] = self.folder.get()
        config['toggle_case']['lower_case'] = self.lower.get()
        config['toggle_case']['preview'] = self.ex_upper.get()
        with open(config_path, 'w', encoding='utf-8') as file:
            yaml.dump(config,file,default_flow_style=False, allow_unicode=True,encoding='utf-8',sort_keys=True)
        self.master.destroy()  # 销毁窗口  
if __name__ == '__main__':
    #app = Tk()
    theme=config['global'].get('theme','sandstone')
    app = ttk.Window(themename=theme)
    sw = app.winfo_screenwidth()
    sh = app.winfo_screenheight()
    x = (sw-windows_width)/2
    y = (sh-windows_heigh)/2
    app.geometry("%dx%d+%d+%d" %(windows_width,windows_heigh,x,y)) # 设置窗口大小
    app.title('文件批量改名工具')
    #app.resizable(0,0)# 不可调整窗口大小
    #app.minsize(sw, sh)# 设置窗口最小大小
    #app.iconbitmap('logo.ico')logo
    Application(master=app)
    app.mainloop()